package seatiger.tomcat.coyote.http11.filters;

import seatiger.tomcat.coyote.OutputBuffer;
import seatiger.tomcat.coyote.Response;
import seatiger.tomcat.coyote.http11.OutputFilter;
import seatiger.tomcat.util.buf.ByteChunk;
import seatiger.tomcat.util.buf.HexUtils;

import java.io.IOException;

/**
 * 块输出过滤器
 *
 * 主要用于http1.1协议，如果返回报文头没有指定content-length
 * 那么就使用chunked
 */
public class ChunkedOutputFilter implements OutputFilter {

    protected OutputBuffer buffer;

    protected byte[] chunkLength;

    /**
     * Chunk header.
     */
    protected ByteChunk chunkHeader = new ByteChunk();


    /**
     * END Chunked 0/r/n/r/n
     */
    protected static final ByteChunk END_CHUNK = new ByteChunk();

    static {
        byte[] END_CHUNK_BYTES = {(byte) '0', (byte) '\r', (byte) '\n',
                (byte) '\r', (byte) '\n'};
        END_CHUNK.setBytes(END_CHUNK_BYTES, 0, END_CHUNK_BYTES.length);
    }

    public ChunkedOutputFilter() {
        chunkLength = new byte[11];
        chunkLength[8] = (byte) '\r';
        chunkLength[9] = (byte) '\n';
    }

    @Override
    public int doWrite(ByteChunk chunk, Response res) throws IOException {
        int result = chunk.getLength();
        if (result <= 0) {
            return 0;
        }
        // Calculate chunk header
        int pos = 7;
        int current = result;
        while (current > 0) {
            int digit = current % 16;
            current = current / 16;
            chunkLength[pos--] = HexUtils.HEX[digit];
        }
        //先刷出本地发送的字节个数 b/r/n 就是11个字节
        chunkHeader.setBytes(chunkLength, pos + 1, 9 - pos);
        buffer.doWrite(chunkHeader, res);
        //输出真正的内容
        buffer.doWrite(chunk, res);
        //输出/r/n
        chunkHeader.setBytes(chunkLength, 8, 2);
        buffer.doWrite(chunkHeader, res);
        return result;
    }

    @Override
    public void setResponse(Response response) {

    }

    @Override
    public void recycle() {

    }

    @Override
    public void setBuffer(OutputBuffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public long end() throws IOException {
        //最后没有字节输出了，需要告诉客户端 0/r/n
        buffer.doWrite(END_CHUNK,null);
        return 0;
    }
}
